package com.oop.example.work.bel;

import com.oop.example.utils.Utils;
import com.oop.example.data.EntryPOJO;
import com.oop.example.data.HibernateUtil;
import com.oop.example.xml.LabelDictionary;
import com.oop.example.xml.LabelDictionary.Entry;
import com.oop.example.xml.LingvoXML;
import com.oop.example.xml.LingvoXML.Dictionary;
import com.oop.example.xml.ObjectFactory;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JProgressBar;
import javax.swing.text.JTextComponent;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.hibernate.Query;
import org.hibernate.classic.Session;

/**
 *
 * @author SalAA
 */
public class Exporter {

    private ObjectFactory factory = new ObjectFactory();
    private File exportFile = null;
    private String indexLanguage = "";
    private String contentLanguage = "";
    private String numeratorDictionary = "";
    private String sortingType = "";
    private String dictionaryName = "";
    private JTextComponent indicator = null;
    private boolean labels = false;
    private boolean format = false;
    private JProgressBar progress;
    private boolean stop = false;
    private boolean mergeHomonym = false;
    private boolean mergeHomograph = false;

    public Exporter(File exportFile,
            String indexLanguage,
            String contentLanguage,
            String numeratorDictionary,
            String sortingType,
            String dictionaryName,
            JTextComponent indicator,
            JProgressBar progress,
            boolean labels,
            boolean format,
            boolean megeHomonym,
            boolean megeHomograph) {
        this.exportFile = exportFile;
        this.indexLanguage = indexLanguage;
        this.contentLanguage = contentLanguage;
        this.numeratorDictionary = numeratorDictionary;
        this.sortingType = sortingType;
        this.dictionaryName = dictionaryName;
        this.indicator = indicator;
        this.progress = progress;
        this.labels = labels;
        this.format = format;
        this.mergeHomograph = megeHomograph;
        this.mergeHomonym = megeHomonym;
    }

    public void export() {
        new Thread(new ParsingTask(exportFile)).start();
    }

    public void stop() {
        stop = true;
    }

    private class ParsingTask implements Runnable {

        private LingvoXML xml = factory.createLingvoXML();
        private Dictionary dictionary = factory.createLingvoXMLDictionary();
        private File exportFile = null;

        public ParsingTask(File exportFile) {
            this.exportFile = exportFile;
        }

        @Override
        public void run() {
            int counter = 0;
            int max = 0;
            //Извлечение массива данных из БД
            indicator.setText("Извлечение массива данных из БД");
            ArrayList<EntryPOJO> items = new ArrayList<EntryPOJO>();
            try {
                Session openSession = HibernateUtil.getSessionFactory().openSession();
                Query createQuery = openSession.createQuery("select a from EntryPOJO a order by a.ID");
                System.out.println(createQuery.getQueryString());
                List list = createQuery.list();
                max = list.size();
                progress.setMaximum(max);
                for (Object o : list) {
                    counter++;
                    progress.setValue(counter);
                    if (o instanceof EntryPOJO) {
                        EntryPOJO pojo = (EntryPOJO) o;
                        items.add(pojo);
                        if (stop) {
                            return;
                        }
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace(System.out);
            }
            int count = 0;
            //Формирование массива Entry
            indicator.setText("Парсинг");
            counter = 0;
            max = items.size();
            //TempStore store = new TempStore();
            ParsedEntrys parsedEntrys = new ParsedEntrys();
            for (EntryPOJO pojo : items) {
                counter++;
                progress.setValue(counter);
                progress.setToolTipText("" + counter + " из " + max);
                try {
                    EntryHandler handler = new EntryHandler();
                    handler.setEntryPOJO(pojo);
                    handler.handle();
                    List<com.oop.example.xml.Entry> entryzz = new ArrayList<com.oop.example.xml.Entry>();
                    entryzz.add(handler.getEntry());
                    if (handler.getChildEntrys() != null && !handler.getChildEntrys().isEmpty()) {
                        entryzz.addAll(handler.getChildEntrys());
                    }
                    for (com.oop.example.xml.Entry e : entryzz) {
                        ParsedEntry pe = new ParsedEntry(e);
                        ParsedEntry homograph = parsedEntrys.getHomograph(pe);

                        if (homograph != null) {
                            if (mergeHomograph) {
                                homograph.insertHomograph(pe);
                            } else {
                                System.out.println("ignore homograph>> " + handler.getHeader());
                                parsedEntrys.add(pe);
                            }
                        } else {
                            ParsedEntry homonym = parsedEntrys.getHomonym(pe);
                            if (homonym != null) {
                                if (mergeHomonym) {
                                    homonym.insertHomonym(pe);
                                } else {
                                    System.out.println("ignore homonym>> " + handler.getHeader());
                                    parsedEntrys.add(pe);
                                }
                            } else {
                                parsedEntrys.add(pe);
                            }
                        }
                    }
                } catch (Exception ex) {
                    count++;
                }
                if (stop) {
                    return;
                }
            }
            indicator.setText("Формирование массива статей");
            max = parsedEntrys.size();
            counter = 0;
            for (ParsedEntry e : parsedEntrys) {
                counter++;
                progress.setValue(counter);
                progress.setToolTipText("" + counter + " из " + max);
                dictionary.getEntry().add(e.getEntry());
                if (stop) {
                    return;
                }
            }
            //Формирум словарь помет
            indicator.setText("Заполнение параметров словаря");
            try {
                dictionary.setContentLanguage(contentLanguage);
                dictionary.setDictionaryName(dictionaryName);
                dictionary.setIndexLanguage(indexLanguage);
                dictionary.setNumeratorDictionary(numeratorDictionary);
                dictionary.setSortingType(sortingType);
                if (labels) {
                    Properties labelDictionaryProps = Utils.getLabelDictionary();
                    LabelDictionary labelDictionary = factory.createLabelDictionary();
                    for (String s : labelDictionaryProps.stringPropertyNames()) {
                        //if (!Utils.noLabelLabels.contains(s)) {
                            Entry labelDictionaryEntry = factory.createLabelDictionaryEntry();
                            labelDictionaryEntry.setLabel(s);
                            labelDictionaryEntry.setTranslation(labelDictionaryProps.getProperty(s));
                            labelDictionary.getEntry().add(labelDictionaryEntry);
                        //}
                    }
                    dictionary.setLabelDictionary(labelDictionary);
                }

            } catch (Exception ex) {
                ex.printStackTrace(System.out);
            }


            //Сохранение в файл
            indicator.setText("Сохранение в файл");
            try {
                xml.setVersion(2);
                xml.setDictionary(dictionary);
                JAXBContext ctx = JAXBContext.newInstance(LingvoXML.class);
                Marshaller marshaller = ctx.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, format);
                StringWriter sw = new StringWriter();
                marshaller.marshal(xml, sw);
                StringBuffer sb = null;
                if (format) {
                    sb = removeSpaces(sw.getBuffer());
                } else {
                    sb = sw.getBuffer();
                }
                write(exportFile, sb);
                //marshaller.marshal(xml, exportFile);
            } catch (Exception ex) {
                ex.printStackTrace(System.out);
            }

            //Сохранение словаря с дублями
//            if (finder.getEntrys().size() > 0) {
//                System.out.println("Найдено " + finder.getEntrys().size() + " дубликатов");
//                indicator.setText("Сохранение словаря с дублями");
//                try {
//                    dictionary.getEntry().clear();
//                    for (com.abbyy.xml.Entry e : finder.getEntrys()) {
//                        dictionary.getEntry().add(e);
//                    }
//                    xml.setDictionary(dictionary);
//                    JAXBContext ctx = JAXBContext.newInstance(LingvoXML.class);
//                    Marshaller marshaller = ctx.createMarshaller();
//                    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, format);
//                    File doubleFile = new File(exportFile.getAbsolutePath() + ".double.xml");
//                    marshaller.marshal(xml, doubleFile);
//                } catch (Exception ex) {
//                    ex.printStackTrace(System.out);
//                }
//            } else {
//                System.out.println("Дубликатов не найдено");
//            }


            indicator.setText("Готово! Ошибок разбора: " + count);
        }
    }

    public static StringBuffer removeSpaces(CharSequence htmlString) {
        Pattern patt = Pattern.compile(">( )*(\n)( )*<");
        Matcher m = patt.matcher(htmlString);
        StringBuffer sb = new StringBuffer(htmlString.length());
        while (m.find()) {
            String text = m.group(1);
            text = ">\n<";
            m.appendReplacement(sb, Matcher.quoteReplacement(text));
        }
        m.appendTail(sb);
        return sb;
    }

    public static void write(File f, StringBuffer sb) {
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
            out.write(sb.toString());
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
}
